package SemanticoPacote;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import SemanticoPacote.TratamentoErroSemantico.ErroSemantico;
import compilador_full.TabelaSimbolos;

/**
 *
 * @author Jomas
 */
public class ExpAtribuicao {
      //
      //
      public void  expatribuicao (TabelaSimbolos tabelaSimbolos, String escopo) {
        String tipoDaAtribuicao = "";
        // verifica se é ponteiro
        if (tabelaSimbolos.getLookahead().equals("*")) {
             tabelaSimbolos.soConsome(); // consome o *
        }
        //
        // verifica se o nome existe
        if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {
            System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada +");
             ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha()
                                            + ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  não foi declarada " );
        } else {
            // define o tipo da variável
            if (tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead()).equals(""))
                // existe tipo
                tipoDaAtribuicao = tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo);
            else
                tipoDaAtribuicao = tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead());
        }
        //

        // reconhece o <nome>
        tabelaSimbolos.soConsome();
        // verifica se é atribuição
        if (tabelaSimbolos.getLookahead().equals("=")) {
            tabelaSimbolos.soConsome(); // consome o igual

            // chama depois da atribuição = ...
            depoisDoIgual(tabelaSimbolos, escopo, tipoDaAtribuicao);

        // verifica se é um incremento/decremento
        } else if (tabelaSimbolos.getLookahead().equals("++") || tabelaSimbolos.getLookahead().equals("--")) {
            tabelaSimbolos.soConsome(); // consome o ++ | --
            tabelaSimbolos.soConsome(); // consome o ;

        // verifica se é struct
        } else if (tabelaSimbolos.getLookahead().equals("->") || tabelaSimbolos.getLookahead().equals(".")) {
            tabelaSimbolos.soConsome(); // -> ou .

            // Chama acesso struct
            //acessoStruct acessostruct = new acessoStruct();
            //acessostruct.acessoStruct(tabelaSimbolos, String escopo, tipoDaAtribuicao);
            //
            // chama depois da atribuição = ...
            depoisDoIgual(tabelaSimbolos, escopo, tipoDaAtribuicao);

        // verifica se é vetor
        } else if (tabelaSimbolos.getLookahead().equals("[")) {
                // enquanto for vetor verifique se o que ta dentro é inteiro ou se a variável ta declarada
                while(tabelaSimbolos.getLookahead().equals("[")) {
                    if(tabelaSimbolos.reconhecer("[")) {          // reconhece [
                        //
                        if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {
                            System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada");
                             ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha()
                                                            + ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  não foi declarada " );
                        } else {
                            // define o tipo da variável é inteiro ou numero
                            if (tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead()).equals("int") ||
                                    tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead()).equals("int") ||
                                    tabelaSimbolos.getTipo().equals("numero") )
                            {

                                if (tabelaSimbolos.getTipo().equals("numero"))
                                    if (!InformaTipo(tabelaSimbolos.getLookahead()).equals("int")) {
                                        System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não é inteiro a variável dentro do vetor");
                                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Não é inteiro a variável dentro do vetor : " + tabelaSimbolos.getLookahead());
                                    }
                                //
                            } else {
                                System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada");
                                ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha()
                                            + ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  não foi declarada " );
                            }
                        }
                        // so consome
                        tabelaSimbolos.soConsome(); // consome o valor dentro do [ ]
                        tabelaSimbolos.soConsome(); // consome o ]
                    }
                  //
                }
                //
                // chama depois da atribuição = ...
             depoisDoIgual(tabelaSimbolos, escopo, tipoDaAtribuicao);
        }

      }
      //

      // verifica depois da igualdade
      public void depoisDoIgual (TabelaSimbolos tabelaSimbolos, String escopo, String tipoDaAtribuicao) {

                // chama chamadaDeFuncao
                if (tabelaSimbolos.getTipo().equals("identificador") && tabelaSimbolos.superLookahead(1).equals("(")) {

                    // chama expressao aritimetica
                    ExpressaoAritmetica expressaoaritmetica = new ExpressaoAritmetica();
                    expressaoaritmetica.expAritmetica(tabelaSimbolos, escopo, tipoDaAtribuicao);
                    tabelaSimbolos.soConsome(); // consome o ;

                // chama Struct
                } else if (tabelaSimbolos.getLookahead().equals("->") || tabelaSimbolos.getLookahead().equals(".")) {

                    // Chama acesso struct
                    //acessoStruct acessostruct = new acessoStruct();
                    //acessostruct.acessoStruct(tabelaSimbolos, escopo, tipoDaAtribuicao);

                // verifica se é a = 1;
                } else if (tabelaSimbolos.getTipo().equals("numero") && tabelaSimbolos.superLookahead(1).equals(";")) {

                    // verifica se os tipos são iguais
                    if (! tipoDaAtribuicao.equals(InformaTipo(tabelaSimbolos.getLookahead())) && !tipoDaAtribuicao.equals("")) {
                        System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + InformaTipo(tabelaSimbolos.getLookahead()));
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    tabelaSimbolos.soConsome(); // consome o numero
                    tabelaSimbolos.soConsome(); // consome o ;

                // verifica se é a = b;
                }  else if (tabelaSimbolos.getTipo().equals("identificador") && tabelaSimbolos.superLookahead(1).equals(";")) {
                    String TipoAtual = "";
                    // verifica se o nome existe
                    if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {
                        System.out.println(" ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada +");
                         ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha()
                                                        + ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  não foi declarada " );
                    } else {
                        // define o tipo da variável
                        if (tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead()).equals("")) {
                            // existe tipo
                            TipoAtual = tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo);
                        } else {
                            TipoAtual = tabelaSimbolos.RetornaTipoDeGlobalDeclarada(tabelaSimbolos.getLookahead());

                        }
                    }
                    //
                    if (!TipoAtual.equals(tipoDaAtribuicao) && !tipoDaAtribuicao.equals("") && !TipoAtual.equals("")) {
                         System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + TipoAtual);
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    //
                    tabelaSimbolos.soConsome(); // consome o nome
                    tabelaSimbolos.soConsome(); // consome o ;

                // verifica se é uma expressão
                } else if ((tabelaSimbolos.getTipo().equals("identificador") || tabelaSimbolos.getTipo().equals("numero")) && tabelaSimbolos.superTipo(1).equals("operador")) {
                    // chama expressao aritimetica
                    ExpressaoAritmetica expressaoaritmetica = new ExpressaoAritmetica();
                    expressaoaritmetica.expAritmetica(tabelaSimbolos, escopo, tipoDaAtribuicao);
                    tabelaSimbolos.soConsome(); // consome o ;

                // verifica se é um boolean
                } else if ((tabelaSimbolos.getLookahead().equals("true") || tabelaSimbolos.getLookahead().equals("false")) && tabelaSimbolos.superLookahead(1).equals(";")) {
                    // verifica se os tipos são iguais
                    if (! tipoDaAtribuicao.equals(InformaTipo(tabelaSimbolos.getLookahead())) && !tipoDaAtribuicao.equals("")) {
                        System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + InformaTipo(tabelaSimbolos.getLookahead()));
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    tabelaSimbolos.soConsome(); // consome o true|false
                    tabelaSimbolos.soConsome(); // consome o ;

                 // verifica se é um caracter
                } else if (tabelaSimbolos.getTipo().equals("frase") && tabelaSimbolos.getLookahead().length() == 3 && tabelaSimbolos.superLookahead(1).equals(";")) {

                    // verifica se os tipos são iguais
                    if (! tipoDaAtribuicao.equals(InformaTipo(tabelaSimbolos.getLookahead())) && !tipoDaAtribuicao.equals("")) {
                        System.out.println(" ERRO SEMANTICO - Tipos diferentes :"+ tipoDaAtribuicao + " != " + InformaTipo(tabelaSimbolos.getLookahead()));
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha  " +tabelaSimbolos.getLinha() +
                                ". Descrição: Variável  " + tabelaSimbolos.getLookahead() + "  incompatível com tipo    " + tipoDaAtribuicao);
                    }
                    tabelaSimbolos.soConsome(); // consome o caracter
                    tabelaSimbolos.soConsome(); // consome o ;
                }
      }



      // verifica se o numero é inteiro
      public String InformaTipo (String token) {
          // informa tipo
          if (token.equals("true") || token.equals("false"))
              return "boolean";
          if (token.charAt(0) == '\"' && token.length() > 3)
              return "frase";
          if (token.charAt(0) == '\"' && token.length() == 3)
              return "char";
          if (token.charAt(0) == '0' || token.charAt(0) == '1' || token.charAt(0) == '2' || token.charAt(0) == '3' || token.charAt(0) == '4' || token.charAt(0) == '5' ||
                  token.charAt(0) == '6' || token.charAt(0) == '7' || token.charAt(0) == '8' || token.charAt(0) == '9') {
              // verifica se o numero é inteiro
              for (int i = 0; i < token.length(); i++)
                    if (token.charAt(i) == '.') // se encontrar . é por que é float
                            return "float";
              // retorna se é um numero
              return "int";
          } else {
              return "variavel";
          }
      }
}